/*****************************************************************************
* visualSTATE Main Loop Source File (sample code) targeted for an Atmel
* AVR Mega103 microcontroller.
*
* The file contains an implementation for a main loop using the visualSTATE
* basic API. 
*
* The code uses a static queue for storing events. The functions for inter-
* facing to the queue are described in the sample code file 
* simpleEventHandler.h.
*
* The file contains calls which uses stdin and stdout. If these streams do
* not exist on a specific target, replace such calls with appropriate code.
*****************************************************************************/

/* *** include directives *** */

#include <stdio.h>
#include <stdlib.h>

#include "SEMLibB.h"

/*  The below include directives contains declarations for a visualSTATE 
    project/system called MY_System. To use a different visualSTATE project, 
    just replace the includes. */

#include "System1Action.h"
#include "System1Data.h"

/*  This file is included in order to use an event queue with static size.
    In order to use a queue with dynamic size, include the header file
    advancedEventHandler.h and replace 'SEQ_' with 'DEQ_' in all calls to 
    functions with prefix 'SEQ_'. Also, the call to function
    DEQ_Uninitialize should be uncommented. */

#include "simpleEventHandler.h"

/*  User include directives for an Atmel Mega103 target and the LED system
    drivers */    




/* *** macro definitions *** */

/** Macro value used in call to OS_Wait. Specifies an infinite duration. */
#define INFINITE -1

/** Macro value used in call to OS_Wait. Specifies a condition which is TRUE
    when one or more events are pending. */
#define OS_VS_EVENT_PENDING 0


/* *** function declarations *** */

/** Uninitialize all. This function must be called just before program
    exit in order to free allocated resources (in this case the memory
    allocated by the dynamic event handler). */
void UninitializeAll (void);

/** Handle error. Whenever an error is detected, this function must be called.
    In this implementation it forces a program exit, which might not be the
    best solution in all cases. The value returned by exit is the value
    of the detected error. */
void HandleError (unsigned char ccArg);
    
/** Operating system wait. The function mimics an operating system call,
    which is used by processes entering the wait state. The parameter waitArg
    informs the OS of a condition to be fulfilled before putting the calling
    process back into the active state. The parameter duration informs the OS
    how long the calling process is prepared to wait for the condition to come
    TRUE.
    In this implementation both parameters are ignored. */
void OS_Wait (unsigned char waitArg, int duration);

/** Operating system visualSTATE process. Mimics a OS process for a 
    visualSTATE system. In this implementation this is the mainloop inter-
    facing to the visualSTATE basic API. */
void OS_VS_Process (void);


/* *** variable definitions *** */

/* Define completion code variable. */
unsigned char cc;


/* *** function definitions *** */

void UninitializeAll (void)
{
//  call DEQ_Uninitialize();, if you use the dynamic event queue instead of the simple.
}


void HandleError (unsigned char ccArg)
{
//  printf("Error code %i detected, exiting application.\n", ccArg);
//  UninitializeAll();
//  exit(ccArg);
}


#if 0
/*  Use OS_Wait to simulate your system using the IAR C-SPY simulator
    or other source level simulator */
void OS_Wait (unsigned char waitArg, int duration)
{
  /*  Ignore the parameters; just retrieve events from the 
      keyboard and put them into the queue. When 
      EVENT_UNDEFINED is read from the keyboard, return 
      to the calling process. */
  SEM_EVENT_TYPE event;

  printf("Putting the OS_VS_Process into the wait state.\n");
  printf("Type in event numbers and press return for each one.\n");
  printf("Typing %i will end the input sequence.\n", EVENT_UNDEFINED);

  do
  {
    printf(":");
    scanf("%i", &event);
    if (event != EVENT_UNDEFINED)
    {
      if ((cc = SEQ_AddEvent(event)) != UCC_OK)
        HandleError(cc);
    }
  }
  while (event != EVENT_UNDEFINED || !SEQ_EventPendingP());
  printf("Putting the OS_VS_Process into the active state.\n");
}
#endif
extern void GetEvent(void);
/* Define action expression variable. */
static SEM_ACTION_EXPRESSION_TYPE actionExpressNo;

/* Define and initialize. In this case the reset event is SE_RESET. */
static SEM_EVENT_TYPE eventNo = SE_RESET;

void Fsm_init(void)
{
  /* Define action expression variable. */
//  SEM_ACTION_EXPRESSION_TYPE actionExpressNo;

  /* Define and initialize. In this case the reset event is SE_RESET. */
//  SEM_EVENT_TYPE eventNo = SE_RESET;

  /* Initialize the VS System. */
//  SEM_InitAll();
  VSInitAll();

  /* Initialize project external variables if used... */

  /* Initialize event queue */
  SEQ_Initialize(); 

  /* Add the reset event. It may also be added to the queue by some other means but it should be the first event */
  SEQ_AddEvent(SE_RESET);

}

void Fsm_deal(void)
{
  /* Do forever */
  
    /* Get next event from queue */	  
    if (SEQ_RetrieveEvent(&eventNo) != UCC_QUEUE_EMPTY)
    {     
      /* Deduct the event. */
      if ((cc = VSDeduct(eventNo)) != SES_OKAY)
        HandleError(cc);
      
      /* Get resulting action expressions and execute them. */
      while ((cc = SEM_GetOutput(&actionExpressNo)) == SES_FOUND)
        SEM_Action(actionExpressNo);
      if (cc != SES_OKAY)
        HandleError(cc);
      
      /* Change the next state vector. */
      if ((cc = SEM_NextState()) != SES_OKAY)
        HandleError(cc);
    }    
#if 0
    /* Use OS_Wait to simulate events occuring in your system */
    OS_Wait (OS_VS_EVENT_PENDING, INFINITE);
#else
    /* Use scanInputs if program running on the actual hardware */ 
	else 
		{
		GetEvent();
		}

#endif        
  
}

